/*
* @Author: hong
* @Description:简单的用鼠标旋转对象的脚本，具有旋转速度和灵敏度等自定义选项
* @Date: 2024年04月16日 星期二 16:04:32
* @Modify:
*/

using UnityEngine;
using UnityEngine.EventSystems;

namespace SCore.UI
{
    public class RotateObjectWithMouse : MonoBehaviour
    {
        public bool _isIgnoreUI = false;

        public float _modelRotationFilter = 30.0f;
        public float _modelRotationSpeedFilter = 5.0f;
        public float _modelRotationCumulativeDecay = 100.0f;
        public float _modelDragSensitivity = 360.0f;
        private bool _isDraggingModel;
        private float _modelRotation;
        private float _modelRotationTarget;
        private float _modelRotationSpeed;
        private float _modelRotationCumulative;

        private Vector3 _lastMousePosition;
        private Quaternion initialRotation; // 存储初始旋转
        private bool isResettingRotation; // 是否正在重置旋转

        private void Start()
        {
            // 在脚本启动时存储初始旋转
            initialRotation = transform.localRotation;
        }

        // Update is called once per frame
        void Update()
        {
            if (!_isIgnoreUI)
            {
#if UNITY_EDITOR
                if (EventSystem.current.IsPointerOverGameObject() && !_isDraggingModel)
#else
       if (Input.touchCount > 0 && EventSystem.current.IsPointerOverGameObject(Input.GetTouch(0).fingerId) && !_isDraggingModel)
#endif
                {
                    return;
                }
            }

            // 获取鼠标当前位置
            Vector3 mousePosition = Input.mousePosition;

            // 在鼠标按下时，记录鼠标位置
            if (Input.GetMouseButtonDown(0))
            {
                _lastMousePosition = mousePosition;
                OnModelPressed(true);
            }

            // 当鼠标左键按下时，计算鼠标位置的变化
            if (Input.GetMouseButton(0))
            {
                Vector3 deltaMouse = mousePosition - _lastMousePosition;

                OnModelDragged(deltaMouse);
                // transform.Rotate(Vector3.up * deltaMouse.x * rotationSpeed, Space.World);
            }

            if (Input.GetMouseButtonUp(0))
            {
                OnModelPressed(false);
            }

            // 更新上一帧的鼠标位置
            _lastMousePosition = mousePosition;

            UpdateModelRotation();
        }

        private void UpdateModelRotation()
        {
            // 当对象停止转动时缓慢归为初始旋转状态
            if (!_isDraggingModel && Mathf.Abs(_modelRotationSpeed) < 0.01f && !isResettingRotation)
            {
                StartResettingRotation();
            }

            // 如果正在重置旋转，执行重置逻辑
            if (isResettingRotation)
            {
                ContinueResettingRotation();
            }
            else
            {
                if (!_isDraggingModel)
                {
                    _modelRotationSpeed =
                        Mathf.Lerp(_modelRotationSpeed, 0, _modelRotationSpeedFilter * Time.deltaTime);
                    _modelRotationTarget += _modelRotationSpeed * Time.deltaTime;
                }

                _modelRotationCumulative += Mathf.Abs(_modelRotationSpeed) * Time.deltaTime;
                _modelRotationCumulative =
                    Mathf.Max(0, _modelRotationCumulative - _modelRotationCumulativeDecay * Time.deltaTime);
                _modelRotation =
                    Mathf.LerpAngle(_modelRotation, _modelRotationTarget, _modelRotationFilter * Time.deltaTime);
                this.transform.localRotation = Quaternion.AngleAxis(_modelRotation, Vector3.up);
            }
        }

        private void OnModelDragged(Vector2 delta)
        {
            float screenDeltaX = delta.x / Screen.width;
            float rotationDelta = -screenDeltaX * _modelDragSensitivity;
            _modelRotationTarget += rotationDelta;

            if (Time.deltaTime > float.Epsilon)
            {
                _modelRotationSpeed = rotationDelta / Time.deltaTime;
            }
            else
            {
                _modelRotationSpeed = 0.0f;
            }
        }

        private void OnModelPressed(bool pressed)
        {
            _isDraggingModel = pressed;
        }


        // 开始重置旋转的函数
        private void StartResettingRotation()
        {
            isResettingRotation = true;
            _modelRotationTarget = 0f; // 重置目标旋转角度
            _modelRotationSpeed = 0f; // 重置旋转速度
            _modelRotationCumulative = 0f; // 重置累积旋转
        }

        // 持续重置旋转的函数
        private void ContinueResettingRotation()
        {
            // 计算新的旋转角度和速度
            _modelRotation = Mathf.LerpAngle(_modelRotation, 0f, _modelRotationFilter * Time.deltaTime);
            _modelRotationSpeed = Mathf.Lerp(_modelRotationSpeed, 0f, _modelRotationSpeedFilter * Time.deltaTime);

            // 应用旋转
            this.transform.localRotation = Quaternion.AngleAxis(_modelRotation, Vector3.up);

            // 如果旋转速度接近零并且当前旋转接近初始旋转，则停止重置
            if (Mathf.Abs(_modelRotationSpeed) < 0.01f &&
                Quaternion.Angle(transform.localRotation, initialRotation) < 1f)
            {
                isResettingRotation = false;
            }
        }
    }
}